Yacon.util.LinkList = function()
{
 	this.firstElement   = null;	
 	this.lastElement    = null;
 	this.activeElement  = null;	
 	this.length         = 0;   
		
}
Yacon.util.LinkList.Extend(Object,{

	insert:function(mode, element, newElement)
	{
		var element1, element2;
		switch (mode)
		{
			case "begin":{
				element1 = null;
				element2 = this.firstElement;
				break;
			}
			case "before":{
				element1 = (element)?element.prevElement:null;
				element2 = element;
				break;
			}
			case "after":{
				element1 = element;
				element2 = (element)?element.nextElement:null;
				break;
			}
			default:{
				element1 = this.lastElement;
				element2 = null;
				break;
			}
		}

		newElement.prevElement = element1;
		newElement.nextElement = element2;
		
		if (element1) element1.nextElement = newElement; else this.firstElement = newElement;
		if (element2) element2.prevElement = newElement; else this.lastElement  = newElement;
		
		this.length++;
		this.activeElement = newElement;
	},
	append:function(element)
	{
		if (this.activeElement){
			this.insert("after",this.activeElement,element);
		}else{
			this.insert("begin",null,element);
		}
	},
	put:function(element)
	{
		if (this.activeElement){
			this.insert("before",this.activeElement,element);
		}else{
			this.insert("begin",null,element);
		}
	},
	move:function(element1,element2)
	{
		var tempElement;
		if (element1 && element2 )
		{
			tempElement = element1;		
			
			element1.nextElement = element2.nextElement;
			element1.prevElement = element2.prevElement;
			element1 = element2; 			
			element2.nextElement = tempElement.nextElement;
			element2.prevElement = tempElement.prevElement;
			element2 = tempElement;	
		}
	},

	insertSub:function(mode, element, subPObj)
	{
		if (Yacon.isEmpty(subPObj) || Yacon.isEmpty(subPObj.firstElement)) return;
		var element1, element2;
		switch (mode)
		{
			case "begin":{
				element1 = null;
				element2 = this.firstElement;
				break;
			}
			case "before":{
				element1 = (element)?element.prevElement:null;
				element2 = element;
				break;
			}
			case "after":{
				element1 = element;
				element2 = (element)?element.nextElement:null;
				break;
			}
			default:{
				element1 = this.lastElement;
				element2 = null;
				break;
			}
		}
		subPObj.firstElement.prevElement = element1;
		subPObj.lastElement.nextElement  = element2;
		
		if (element1) element1.nextElement = subPObj.firstElement; else this.firstElement = subPObj.firstElement;
		if (element2) element2.prevElement = subPObj.lastElement;  else this.lastElement  = subPObj.lastElement;
		
		this.length += subPObj.length;
	},
	deleteElement:function(element)
	{
		if (Yacon.isEmpty(element))
			return;
		
		var element1, element2;
		element1 = element.prevElement;
		element2 = element.nextElement;
		if(Yacon.isEmpty(element1) && Yacon.isEmpty(element2)){
			return ;
		}
		
		if (element1){ 
			element1.nextElement = element2; 
		}else{ 
			this.firstElement    = element2;
		}
		if (element2)
		{
			element2.prevElement = element1;
		}else{ 
			this.lastElement      = element1;
		}
		if (element == this.activeElement)
		{
			if (element2)
				this.activeElement = element2;
			else
				this.activeElement = element1;
		}
		if (element.free)
			element.free();
		
		element = null;
		delete element;

		this.length--;
	},
	isFirst:function()
	{
		return this.activeElement == this.firstElement;
	},
	first:function()
	{
		this.activeElement  = this.firstElement;
		return this.activeElement;
	},
	beforeFirst:function()
	{
		this.activeElement  = null;
	},
	isLast:function()
	{
		return this.activeElement == this.lastElement;
	},
	last:function()
	{
		this.activeElement = this.lastElement; 
		return this.activeElement;
	},
	next:function()
	{
		if (!this.isLast()) 
		{
			if (this.activeElement)
				this.activeElement = this.activeElement.nextElement;
			else
				this.activeElement  = this.firstElement;
			
	        return true;
	     } else 
	     {
	    	 return false;
	     }
	},
	previous:function()
	{
		if (!this.isFirst()) 
		{
			if (this.activeElement)
				this.activeElement = this.activeElement.prevElement;
			else
				this.activeElement  = this.lastElement;
			
	        return true;
	     } else 
	     {
	    	 return false;
	     }
	},
	
	clear:function()
	{
		var element = this.firstElement;
		var _element;
		while (element)
		{
			_element = element;
			element  = element.nextElement;
			if (_element.free)
				_element.free();
			_element = null;
			delete _element;
		}
		this.activeElement = null;
		this.firstElement = null;
		this.lastElement  = null;
		this.length		  = 0;
	}
});

Yacon.util.Container = function()
{
	this.fAttributes    =  new Yacon.util.Container.Record();	
}

Yacon.util.Container.Extend(Yacon.util.LinkList,
{
	createRecord :function()
	{
		this.insert("last",null,new Yacon.util.Container.Record());
	},
	getAttrValue:function(attrName)
	{
		return this.fAttributes.getFieldValue(attrName);
	},
	setAttrValue:function(attrName,attrValue){
		return this.fAttributes.setFieldValue(attrName,attrValue);
	},
	getFieldValue:function(fieldName)
	{
		if(this.activeElement)
			return this.activeElement.getFieldValue(fieldName);
		else
			return "";
	},
	setJsonStr :function(jsonStr)
	{
		if (Yacon.isEmpty(jsonStr))
			return;
		try{
			var obj = eval(jsonStr);
			if (obj.attr)
				this.fAttributes.jsonList = obj.attr;
			
			if (obj.fields)
			{
				for(var i=0;i<obj.fields.length;i++)
				{
					this.createRecord();
					this.activeElement.jsonList = obj.fields[i];
				}
			}
			this.beforeFirst();
		}catch(e)
		{}
	},
	free: function()
	{
		this.fAttributes.free();
		this.clear();
	}
});


Yacon.util.Container.Record = function()
{
	this.fieldNames    =  new Array();
	this.fieldList     =  new Array();
	this.jsonList      =  null;
	this.factvieField  =  null;
}
Yacon.util.Container.Record.Extend(Object,{
	
	addField :function(field)
	{
		if (Yacon.isEmpty(field))
			return;
		
		if (Yacon.isEmpty(field.getFieldName()))
			return;
		
		var index = this.fieldNames.indexOf(field.getFieldName().toLowerCase());
	    if (index>-1)
		{
			field.setRecord(this);
			this.fieldList[index] = field;
		}else
		{
			 field.setRecord(this);			 
			this.fieldNames.add(field.getFieldName().toLowerCase());
			this.fieldList.add(field);
		}
	    this.factvieField = field;
	},
	getField: function(fieldIndex)
	{
		if (Yacon.isEmpty(fieldIndex))
			return this.factvieField;
		else
			this.factvieField = null;
		
		if (Yacon.isNumber(fieldIndex))
		{
			this.factvieField = this.fieldList.get(fieldIndex);
			 
	    }else  if (Yacon.isString(fieldIndex))
	    {
	    	var index = this.fieldNames.indexOf(fieldIndex.toLowerCase());
		    if (index>-1)
			{
		    	this.factvieField = this.fieldList.get(index);
			}
	    }
		return this.factvieField;	
	},
	getFieldValue: function(fieldIndex)
	{
		if (this.getField(fieldIndex) == null)
		{
			var fieldValue = "";
			if (this.jsonList != null && Yacon.isString(fieldIndex))
				fieldValue = this.jsonList[fieldIndex];
			
			if (fieldValue == null)
				fieldValue = "";
			return fieldValue;
			
		}else
		{
			return this.factvieField.getFieldValue();
		}
	},
	setFieldValue: function(fieldName,fieldValue)
	{
		if (this.getField(fieldName) == null)
			this.creatField(fieldName,fieldValue);
		else
			this.factvieField.setFieldValue(fieldValue);
	},
	creatField: function(fieldName,fieldValue)
	{
		if (Yacon.isEmpty(fieldName))
			return null;
		
		this.factvieField = new Yacon.util.Container.Field();
		this.factvieField.setFieldName(fieldName);
		this.factvieField.setFieldValue(fieldValue);
		this.addField(this.factvieField);
		return this.factvieField;
	},	
	free: function()
	{
		this.fieldNames.clear();
		this.fieldList.clear();
	}	
});

Yacon.util.Container.Field = function()
{
	this.fFieldName    = "";
	this.fFieldValue   = "";
	this.fRecord       = null;
}

Yacon.util.Container.Field.Extend(Object,{
	
	getFieldName :function()
	{
		return this.fFieldName;
	},
	setFieldName:function(fieldName)
	{
		if(fieldName)
			this.fFieldName = fieldName;
	},
	getFieldValue:function()
	{
		return this.fFieldValue + "";
	},
	setFieldValue:function(fieldValue)
	{
		this.fFieldValue = fieldValue;
	},
	getRecord:function()
	{
		return this.fRecord;
	},
	setRecord:function(record)
	{
		this.fRecord = record;
	}
});

